﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Caching;
using BSF.Extensions;
using BSF.Tool;
using HuntingFishGame.ManageDomain.BLL.WeChat;
using Newtonsoft.Json;

namespace HuntingFishGame.ManageDomain.BLL.WeChat
{
    /// <summary>
    /// 应用授权作用域
    /// 1 第一步：用户同意授权，获取code
    /// 2 第二步：通过code换取网页授权access_token
    /// 3 第三步：刷新access_token（如果需要）
    /// 4 第四步：拉取用户信息(需scope为 snsapi_userinfo)
    /// 5 附：检验授权凭证（access_token）是否有效
    /// 网页授权获取用户基本信息
    /// http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
    /// </summary>
    public static class WeChatUrlBLL
    {
        /// <summary>
        /// 【step1 / step2】获取授权验证地址
        /// <para> 这一步发送之后，客户会得到授权页面，无论同意或拒绝，都会返回redirectUrl页面。 </para>
        /// <para> 如果用户同意授权，页面将跳转至 redirect_uri/?code=CODE&amp;state=STATE。这里的code用于换取access_token（和通用接口的access_token不通用）</para>
        /// <para> 若用户禁止授权，则重定向后不会带上code参数，仅会带上state参数redirect_uri?state=STATE</para>
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="redirectUrl"></param>
        /// <param name="state">用于保持请求和回调的状态，授权请求后原样带回给第三方。该参数可用于防止csrf攻击（跨站请求伪造攻击），建议第三方带上该参数，可设置为简单的随机数加session进行校验.最多128字节</param>
        /// <param name="scope">应用授权作用域(简单授权snsapi_base | 弹出授权snsapi_userinfo)</param>
        /// <param name="responseType"></param>
        /// <returns>回调地址</returns>
        public static string GetAuthorizeUrl(string appId, string redirectUrl, string state, OAuthScope scope, string responseType = "code")
        {
            var url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}#wechat_redirect",
                                appId, HttpUtility.UrlEncode(redirectUrl), responseType, scope, state);

            // 授权后跳转：redirect_uri/?code=CODE&state=STATE
            return url;
        }

        /// <summary>
        /// 【step2 / step2】根据授权的code票据，获取AccessToken
        /// <code>
        /// {
        /// "access_token":"ACCESS_TOKEN",
        ///  "expires_in":7200,
        ///  "refresh_token":"REFRESH_TOKEN",
        ///  "openid":"OPENID",
        ///  "scope":"SCOPE",
        ///  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
        /// }
        /// </code>
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="secret"></param>
        /// <param name="code">code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。</param>
        /// <param name="grantType"></param>
        /// <returns></returns>
        public static OAuthAccessTokenResult GetUserAccessToken(string appId, string secret, string code, string grantType = "authorization_code")
        {
            var url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type={3}",
                                appId, secret, code, grantType);

            return WebUrlHelper.DoGet<OAuthAccessTokenResult>(url);
        }

        /// <summary>
        /// 检验授权凭证（access_token）是否有效
        /// </summary>
        /// <param name="accessToken">网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同</param>
        /// <param name="openId"></param>
        /// <returns></returns>
        public static bool CheckToken(string accessToken, string openId)
        {
            var url = string.Format("https://api.weixin.qq.com/sns/auth?access_token={0}&openid={1}", accessToken, openId);

            // 正确时：{ "errcode":0,"errmsg":"ok"}
            // 错误时：{ "errcode":40003,"errmsg":"invalid openid"}
            var result = WebUrlHelper.DoGet<WxJsonResult>(url);
            if (result == null)
            {
                return false;
            }
            return result.errcode == ReturnCodeEnum.请求成功;
        }

        /// <summary>
        /// 刷新access_token（如果需要）
        /// 由于access_token拥有较短的有效期，当access_token超时后，可以使用refresh_token进行刷新，refresh_token拥有较长的有效期（7天、30天、60天、90天），当refresh_token失效的后，需要用户重新授权。
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="refreshToken">填写通过access_token获取到的refresh_token参数</param>
        /// <param name="grantType">填写为refresh_token</param>
        /// <returns></returns>
        public static OAuthAccessTokenResult RefreshToken(string appId, string refreshToken, string grantType = "refresh_token")
        {
            var url = string.Format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={0}&grant_type={1}&refresh_token={2}",
                                appId, grantType, refreshToken);

            return WebUrlHelper.DoGet<OAuthAccessTokenResult>(url);
        }

        ///// <summary>
        ///// 获取授权用户信息
        ///// </summary>
        ///// <param name="accessToken">网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同</param>
        ///// <param name="openId"></param>
        ///// <param name="lang">返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语</param>
        ///// <returns></returns>
        //public static OAuthUserInfo GetOAuthUserInfo(string accessToken, string openId, string lang = "zh_CN")
        //{
        //    var url = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang={2}", accessToken, openId, lang);
        //    return WebUrlHelper.DoGet<OAuthUserInfo>(url);
        //}

        ///// <summary>
        ///// 获取用户基本信息(UnionID机制)
        ///// </summary>
        ///// <param name="accessToken"></param>
        ///// <param name="openId"></param>
        ///// <param name="lang"></param>
        ///// <returns></returns>
        //public static UnionUserInfo GetUnionUserInfo(string accessToken, string openId, string lang = "zh_CN")
        //{
        //    // lang:返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语

        //    var url = string.Format("https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang={2}", accessToken, openId, lang);
        //    return WebUrlHelper.DoGet<UnionUserInfo>(url);
        //}

        #region JSSDK
        /// <summary>
        /// 获取凭证接口
        /// </summary>
        /// <param name="grant_type">获取access_token填写client_credential</param>
        /// <param name="appid">第三方用户唯一凭证</param>
        /// <param name="secret">第三方用户唯一凭证密钥，既appsecret</param>
        /// <returns></returns>
        public static WechatAccessToken GetAppToken(string appid, string secret, string grant_type = "client_credential")
        {
            WechatAccessToken result = null;
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}",
                                    grant_type, appid, secret);
            result = WebUrlHelper.DoGet<WechatAccessToken>(url);
            return result;

            //string TokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
            //var jsonText = WebUrlHelper.HttpGet(string.Format(TokenUrl, AppID, AppSecret), string.Empty);
            //JObject jo = (JObject)JsonConvert.DeserializeObject(jsonText); //JObject.Parse(jsonText);//返回{"access_token":"ACCESS_TOKEN","expires_in":7200}
            //string access_token = string.Empty;
            //if (jo.Property("access_token") == null || jo.Property("access_token").ToString() == "")
            //{ }
            //else access_token = jo["access_token"].ToString();
            //return access_token;
        }

        /// <summary>
        /// JsApiTicket 缓存Key
        /// </summary>
        private static string shareJsApiTicketKey = "shareJsApiTicketKey";

        /// <summary>
        /// 得到jsapi_ticket 如果缓存里时间 超时则重新获取  
        /// </summary>
        /// <returns></returns>
        public static WechatTicket GetAppJsTicket(string accessToken)
        {
            WechatTicket ticket = new WechatTicket();
            object jsApiTicketObj = IISCacheHelper.GetCache(shareJsApiTicketKey);
            if (jsApiTicketObj == null)
            {
                string TokenUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi";
                WechatTicket jsonText = WebUrlHelper.DoGet<WechatTicket>(string.Format(TokenUrl, accessToken), null);
                jsonText.CopyTo<WechatTicket>(ticket);
                IISCacheHelper.SetCache(shareJsApiTicketKey, JsonConvert.SerializeObject(jsonText), 100);

                //string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=" + accessToken + "";
                //string resultString = WebUrlHelper.DoGet(url, null);
                ////logger.Info("请求分享Ticket:" + resultString);
                //if (!string.IsNullOrEmpty(resultString))
                //{
                //    WechatTicket _ticketobj = JsonConvert.DeserializeObject<WechatTicket>(resultString);
                //    ticket = _ticketobj.ticket;
                //    SetCache(shareJsApiTicketKey, ticket, 100);
                //}
            }
            else
            {
                WechatTicket jsonText = JsonConvert.DeserializeObject<WechatTicket>(jsApiTicketObj.ToString());
                jsonText.CopyTo<WechatTicket>(ticket);
            }
            return ticket;

        }

        #endregion

    }
}
